import React, { useState, useEffect, memo } from 'react';
import { connect, Dispatch } from 'umi';

import { Card, Breadcrumb, Tooltip, message } from 'antd';
import Icon from '@/components/Icon';
import CombinedChart from '../Charts';
import CustomFilters from './components/CustomFilters';
import FilterLabel from './components/FilterLabel';
import DrillList from './components/DrillList';
import DrillPath from './components/DrillPath';

import { DATA_ACTION_TYPE, OperatorFilterTypes } from '@/pages/SelfQuery/constants';

import styles from './style.less';

import { isLevelVisualType } from '@/pages/SelfQuery/utils';

import {  IndexDetailItem, IFilter, IModel } from '@/pages/SelfQuery/type';
import { ConnectState } from '@/models/connect';

import { IResponse } from '@/models/connect.d.ts';

interface IndexDetailProps {
  indexDetail: IndexDetailItem;
  dispatch: Dispatch;
  parentTitle: string;
  formFilters: Array<any>;
  widget: any;
  filterConfigs: any;
  drillList: Array<any>;
  drillSelectsArr: any;
  loading?: boolean;
}
const dateFlag = "_time_"

const Widget: React.FC<IndexDetailProps> = memo((props) => {
  const {
    indexDetail,
    dispatch,
    formFilters,
    parentTitle,
    widget,
    filterConfigs,
    drillList,
    drillSelectsArr,
    loading
  } = props;
  const [visible, setVisible] = useState(false); // 显示隐藏筛选边栏

  const [drillSelects, setDrillSelects] = useState<Array<any>>([]); // 下钻选中的值

  const [drillListVisibility, setDrillListVisibility] = useState<boolean>(false); // 是否展示下钻列表

  // 清除查看的指标详情数据 退出查看模式
  const clearIndexDetail = () => {
    dispatch({
      type: 'widget/fetchIndexDetail',
      payload: {},
    });
  };

  // 订阅指标操作   true 目前已订阅 & false 目前未订阅
  const subscribe = (type: boolean) => {
    const tisp = type ? '取消订阅成功' : '订阅成功';
    const dispatchType = type ? 'widget/canelSubscribeWidget' : 'widget/subscribeWidget';

    dispatch({
      type: dispatchType,
      payload: { widgetId: indexDetail.widget.widgetId },
      callback: (res: IResponse) => {
        const { header } = res;
        if (header && header.code === 200) {
          message.success(tisp);

          // 更改本地订阅状态 减少请求次数
          let widget = { ...indexDetail };
          widget.subscribe = !widget.subscribe;
          // 更改指标详情数据
          dispatch({
            type: 'widget/fetchIndexDetail',
            payload: widget,
          });
          // 更新我的订阅列表
          dispatch({
            type: 'subscribe/fetchSubscribeWidgets',
          });
        }
      },
    });
  };

  // 清除关闭已筛选条件标签
  const removeFilter = (index: number) => {
    let formFiltersNew: Array<any> = Object.assign([], formFilters);
    formFiltersNew = formFiltersNew.filter((v: any, idx: number) => idx != index);
    dispatch({
      type: 'widget/fetchData',
      payload: { type: DATA_ACTION_TYPE.filter, pararms: { filters: formFiltersNew } },
    });
  };

  // 展开筛选
  const onCostomFilterOpenChange = () => {
    setVisible(true);
  };

  // 获取下钻的维度
  const setCategory = () => {
    let categorys = [];
    const configs = widget.config;
    let groups: Array<string> = filterConfigs.groups;
    const { drills } = configs;
    if (drills && drills.length > 0) {
      categorys = drills.map((drill: any) => drill.name);
    } else {
      //所有维度
      // categorys = Object.keys(model).filter((m: any) => model[m].modelType == 'category')
    }
    //过滤已经筛选的
    categorys = categorys.filter(
      (c: string) =>
        !groups.includes(c) ||
        drills.filter((f: any) => f.name == c && isLevelVisualType(f.visualType)).length,
    );
    categorys = categorys.map((c: string) => {
      return { label: c, value: c };
    });
    //起别名
    if (drills && drills.length > 0)
      categorys = categorys.map((c: any) => {
        let label = c.label;
        const drillList = drills.filter((drill: any) => drill.name == c.label);
        if (drillList.length > 0) {
          const { alias } = drillList[0].field;
          label = alias == '' ? drillList[0].name : alias;
        }
        return { label: label, value: c.value };
      });
    return categorys;
  };
  const getCurrentColumn = (name: any) => {
    if (name.indexOf(dateFlag) != -1) {
      name = name.split(/(_time_)+(?!.*time_.*)/)[0]
      return name
    }
    return name
  }
  // 下钻数据
  const setDownData = (key: string) => {
    const newDrillList = Object.assign([], drillList);
    const configs = widget.config;
    const { drills, model } = configs;
    let newfilterConfigs = { ...filterConfigs };
    let groups = [...newfilterConfigs.groups];
    //获取下钻所需要的过滤值
    let filters: IFilter[] = [];
    //构建下钻已选中的过滤值
    groups.forEach((group: string) => {
      //获取当前已选的字段的值
      let values: Array<string> = drillSelectsArr
        .map((data: any) => `${data[group]}`)
        .filter((value: any) => value && value != 'undefined');
      if (values.length) {
        let name = group;
        //时间是格式化的需要转换
        name = getCurrentColumn(name)
        let modelVal: IModel = model[name];
        let filter: IFilter;
        if (isLevelVisualType(modelVal.visualType)) {
          filter = {
            name: group,
            operator: OperatorFilterTypes.Regexp,
            type: 'filter',
            value: values.join('|'),
            sqlType: 'STRING',
            visualType: modelVal.visualType, //层级类型的数据，前端只保存下钻回退的历史路径，后端只会获取最后一次下钻路径的值
            action: DATA_ACTION_TYPE.drills, //指明是下钻类型的筛选
          };
          //非当前层级下钻的层级数据不按下一级层级下钻
          if (group != key) {
            filter.isLevelFilter = false;
          }
        } else {
          filter = {
            name: group,
            operator: OperatorFilterTypes.In,
            type: 'filter',
            value: values,
            sqlType: 'STRING',
            visualType: modelVal.visualType,
            action: DATA_ACTION_TYPE.drills, //指明是下钻类型的筛选
          };
        }
        filters.push(filter);
      }
    });
    //自定义下钻
    if (drills && drills.length > 0) {
      //判断key是否是别名
      const keys = drills.filter((drill: any) => {
        const { alias } = drill.field;
        return alias != '' && key == alias;
      });
      //获取字段名称（非别名）
      if (keys.length > 0) {
        key = keys[0].name;
      }
    }
    groups.push(key);
    const drillObj = { key: key, filters: filters };
    let filtersPararm: Array<IFilter> = [];
    newDrillList
      .filter((f: any) => f.filters && f.filters.length)
      .map((v: any) => {
        filtersPararm = filtersPararm.concat(v.filters);
      });
    //把重复的下钻值去重
    if (
      !newDrillList.filter(
        (drill: { key: string; filters: Array<IFilter> }) =>
          JSON.stringify(drill) == JSON.stringify(drillObj),
      ).length
    ) {
      newDrillList.push(drillObj);
    }
    dispatch({
      type: 'widget/fetchData',
      payload: {
        type: DATA_ACTION_TYPE.drills,
        drillList: newDrillList,
        pararms: {
          groups: Array.from(new Set(newDrillList.map((v: any) => v.key))),
          filters: filtersPararm.concat(filters),
        },
      },
    });
    onOpenDrillList();
  };

  // 打开或关闭下钻操作列表
  const onOpenDrillList = () => {
    setDrillListVisibility(!drillListVisibility);
  };

  // 展示图表下钻
  const showDataDown = (datas: any) => {
    let selects;
    if (datas && datas.length && datas.length !== 0) {
      selects = datas;
    } else {
      selects = drillSelects;
    }

    if (selects.length === 0) {
      message.warning('请选择下钻路径');
      return;
    }
    if (setCategory().length === 0) {
      message.warning('无可下钻的维度');
      return;
    }

    dispatch({
      type: 'widget/fetchDrillSelectsArr',
      payload: drillSelects,
    });

    onOpenDrillList();
    setDrillSelects(selects)
  };

  // 回退下钻路径
  const removeDrill = (index: number) => {
    //已下钻的集合
    let newDrillList = Object.assign([], drillList);
    //已下钻的集合选中的下标
    if (index < 0) {
      dispatch({
        type: 'widget/fetchData',
        payload: { type: DATA_ACTION_TYPE.drills, pararms: { groups: [], filters: [] } },
      });
    }
    newDrillList = newDrillList.filter((f: any, idx: number) => idx <= index);
    let filtersPararm: Array<IFilter> = [];
    newDrillList
      .filter((f: any) => f.filters && f.filters.length)
      .map((v: any) => {
        filtersPararm = filtersPararm.concat(v.filters);
      });
    dispatch({
      type: 'widget/fetchData',
      payload: {
        type: DATA_ACTION_TYPE.drills,
        drillList: newDrillList,
        pararms: {
          groups: newDrillList.map((v: any) => v.key),
          filters: filtersPararm,
        },
      },
    });
  };

  // 获得操作指标需要的数据  (筛选&下钻) 只需要在加载的时候获取一次
  useEffect(() => {
    dispatch({
      type: 'widget/fetchWidget',
      payload: { id: indexDetail.widget.widgetId, threeSearchVals: '' },
    });
  }, [indexDetail.widget.widgetId]);

  const isWidget = widget.config == undefined ? false : true;
  const drills = isWidget ? setCategory() : [];
  return (
    <div className={styles.indexDetail}>
      <Card
        style={{ width: '100%', height: '100%' }}
        bordered={false}
        title={
          <div>
            <Breadcrumb>
              <Breadcrumb.Item>
                <span className={styles.outtitle} onClick={clearIndexDetail}>
                  {parentTitle}
                </span>
              </Breadcrumb.Item>
              <Breadcrumb.Item>{indexDetail.widget.widgetName}</Breadcrumb.Item>
            </Breadcrumb>
          </div>
        }
        extra={
          <div className={styles.operation}>
            {indexDetail.configs &&
            indexDetail.configs.drills &&
            indexDetail.configs.drills.length > 0 ? (
              <Tooltip title="下钻">
                <span onClick={showDataDown}>
                  <Icon type="drill" width={20} height={20} />
                </span>
              </Tooltip>
            ) : (
              ''
            )}

            {indexDetail.configs &&
            indexDetail.configs.customFilters &&
            indexDetail.configs.customFilters.length > 0 ? (
              <Tooltip title="筛选">
                <span onClick={onCostomFilterOpenChange}>
                  <Icon type="filter" width={24} height={24} />
                </span>
              </Tooltip>
            ) : (
              ''
            )}

            {/* <Tooltip title="分享">
              <span>
                <Icon type="share" width={24} height={24} />
              </span>
            </Tooltip> */}
            <Tooltip title={indexDetail.subscribe ? '点击取消订阅' : '点击订阅'}>
              <span
                onClick={() => {
                  subscribe(indexDetail.subscribe);
                }}
              >
                <Icon
                  type={indexDetail.subscribe ? 'subscribeActive' : 'subscribe'}
                  width={19}
                  height={19}
                />
              </span>
            </Tooltip>
          </div>
        }
      >
        <Card size="small" loading={loading}>
          <CombinedChart
            data={indexDetail.dataRecord.resultList}
            totalDatas={indexDetail.dataRecord.totalDatas}
            columns={indexDetail.dataRecord.columns}
            configs={indexDetail.configs}

            width={500}
            height={300}
            filterConfigs={indexDetail.filterConfigs}
            onSelect={(datas: Array<any>) => {
              setDrillSelects(datas)
            }}
            onLongPress={(datas: Array<any>) => {
              showDataDown(datas);
            }}
            drills={drills}
            name={indexDetail.widget.widgetName}
            isDetails={true}
          />
        </Card>
        {/* 下钻路径展示 */}
        <DrillPath removeDrill={removeDrill} />

        {/* 筛选条件展示 */}
        {formFilters && formFilters.length > 0 && <FilterLabel removeFilter={removeFilter} />}
      </Card>

      {/* 筛选弹框 */}
      <CustomFilters visible={visible} setVisible={setVisible}/>

      {/* 选择下钻类型弹框 */}
      <DrillList
        visibility={drillListVisibility}
        onClose={onOpenDrillList}
        onSure={setDownData}
        dataSource={drills}
      />
    </div>
  );
});

export default connect(({ widget, loading }: ConnectState) => ({
  indexDetail: widget.indexDetail,
  formFilters: widget.formFilters,
  widget: widget.widget,
  drillList: widget.drillList,
  filterConfigs: widget.filterConfigs,
  drillSelectsArr: widget.drillSelectsArr,
  loading: loading.effects['widget/fetchData'],
}))(Widget);
